<template>
  <div class="dg-body">
    <div class="dg-body-fixed-area" ref="dgScrollAreaInstance" @scroll="onVerticalScroll">
      <div class="dg-bg">
        <div class="dg-bg-container">
          <div v-for="node in nodes"
               :key="node.id"
               class="dg-row"
               :class="node.clazz"
               :style="{height: node.height + 'px'}"
               @mouseover="onRowMouseOver(node)" @mouseout="onRowMouseOut(node)" @click="onRowClick(node)"></div>
        </div>
        <div v-if="contentHasScrollBar" :style="{height: scrollBarWidth + 'px'}"></div>
      </div>
      <!--<div class="dg-rows" :style="{height: totalRowsHeight + 'px', width: leftFixedWidth + centerWidth + rightFixedWidth + 'px'}">-->
        <!---->
      <!--</div>-->
      <div class="dg-rows-left">
        <div class="dg-body-left-column" v-for="(col, idx) in leftFixedLeafColumns" :key="col.field" v-if="!col.hide" :style="leftFixedLeafColumnStyles[idx]">
          <d-g-body-cell v-for="node in nodes"
                         :key="node.id"
                         :style="{height: node.height + 'px'}"
                         :column="col"
                         :node="node"
                         :class="node.clazz"
                         :root-config="rootConfig"
                         @check="handleNodeCheck"
                         @mouseover="onRowMouseOver" @mouseout="onRowMouseOut" @click="onRowClick"></d-g-body-cell>
        </div>
      </div>
      <div class="dg-rows-right" :style="{left: leftFixedWidth + centerWidth + 'px', width: rightFixedWidth + 'px'}">
        <div class="dg-body-right-column" v-for="(col, idx) in rightFixedLeafColumns" :key="col.field" v-if="!col.hide" :style="rightFixedLeafColumnStyles[idx]">
          <d-g-body-cell v-for="node in nodes"
                         :key="node.id"
                         :style="{height: node.height + 'px'}"
                         :column="col"
                         :node="node"
                         :class="node.clazz"
                         :root-config="rootConfig"
                         @check="handleNodeCheck"
                         @mouseover="onRowMouseOver" @mouseout="onRowMouseOut" @click="onRowClick"></d-g-body-cell>
        </div>
      </div>
    </div>

    <div class="dg-rows-normal" ref="contentInstance" :style="{left: leftFixedWidth + 'px', width: (contentHasScrollBar ? centerWidth : normalWidth) + 'px'}" @scroll="onHorizontalScroll" @mousewheel="onContentMouseWheel">
      <div style="overflow: hidden; height: 100%;" :style="{width: normalWidth + 'px'}">
        <div class="dg-rows-normal-content" :style="{height: totalRowsHeight + 'px', width: normalWidth + 'px', top: -currentVerticalScroll + 'px'}">
          <div class="dg-body-normal-column" v-for="(col, idx) in normalLeafColumns" :key="col.field" v-if="!col.hide" :style="normalLeafColumnStyles[idx]">
            <d-g-body-cell v-for="node in nodes"
                           :key="node.id"
                           :style="{height: node.height + 'px'}"
                           :column="col"
                           :node="node"
                           :class="node.clazz"
                           :root-config="rootConfig"
                           @check="handleNodeCheck"
                           @mouseover="onRowMouseOver" @mouseout="onRowMouseOut" @click="onRowClick"></d-g-body-cell>
          </div>
        </div>
      </div>
    </div>

    <div class="dg-body-no-data" v-if="isNoData"><span>{{locale.noData}}</span></div>
    <div class="dg-body-loading" v-if="isLoading"><span>{{locale.loading}}</span></div>
  </div>
</template>

<script>
  import _ from 'lodash'
  import Vue from 'vue'
  import DGBodyCell from './DGBodyCell.vue'
  import utils from '../utils'

  let DEFAULT_ROW_HEIGHT = 28

  export default {
    components: {DGBodyCell},
    props: {
      rootConfig: {
        type: Object,
        default () {
          return {}
        }
      },
      isLoading: {},
      leftFixedLeafColumns: Array,
      rightFixedLeafColumns: Array,
      normalLeafColumns: Array,
      dataSource: Array,
      width: Number
    },
    data () {
      return {
        contentHasScrollBar: false,
        nodes: [],
        leftFixedLeafColumnStyles: [],
        rightFixedLeafColumnStyles: [],
        normalLeafColumnStyles: [],
        leftFixedWidth: 0,
        rightFixedWidth: 0,
        normalWidth: 0,
        centerWidth: 0,
        totalRowsHeight: 0,
        currentVerticalScroll: 0,
        scrollBarWidth: utils.scrollBarWidth
      }
    },
    computed: {
      locale () {
        console.log('rootConfig.locale', this.rootConfig.locale)
        return this.rootConfig.locale || {}
      },
      isNoData () {
        return !this.isLoading && (!this.dataSource || this.dataSource.length === 0)
      }
    },
    methods: {
      refreshPosition () {
        let tmpLeftArr = [[], [], []]
        _.forEach([this.leftFixedLeafColumns, this.rightFixedLeafColumns, this.normalLeafColumns], (cols, idx) => {
          let left = 0
          _.forEach(cols, (col, idx01) => {
            tmpLeftArr[idx][idx01] = {left, width: col._width}
            left += col._width
          })
        })
        this.leftFixedWidth = _.sum(_.map(tmpLeftArr[0], e => { return e.width }))
        this.rightFixedWidth = _.sum(_.map(tmpLeftArr[1], e => { return e.width }))
        this.normalWidth = _.sum(_.map(tmpLeftArr[2], e => { return e.width }))
        let centerWidth = this.width - this.leftFixedWidth - this.rightFixedWidth
        this.centerWidth = centerWidth < 0 ? 0 : centerWidth
        this.leftFixedLeafColumnStyles = _.map(tmpLeftArr[0], e => { return {left: `${e.left}px`, width: `${e.width}px`} })
        this.rightFixedLeafColumnStyles = _.map(tmpLeftArr[1], e => { return {left: `${e.left}px`, width: `${e.width}px`} })
        this.normalLeafColumnStyles = _.map(tmpLeftArr[2], e => { return {left: `${e.left}px`, width: `${e.width}px`} })
        this.contentHasScrollBar = centerWidth < this.normalWidth
      },
      initDataSource (val) {
        let newNodes = []
        let totalRowsHeight = 0
        if (val && val.length > 0) {
          _.forEach(val, (item, idx) => {
            let rowHeight = this.rootConfig.rowHeight
            if (rowHeight && rowHeight instanceof Function) {
              rowHeight = rowHeight(item)
            }
            rowHeight = +rowHeight || DEFAULT_ROW_HEIGHT
            totalRowsHeight += rowHeight
            item.$index = idx + 1
            newNodes.push({
              id: this.rootConfig.rowKeyProp && _.get(item, this.rootConfig.rowKeyProp) || idx,
              height: rowHeight,
              selected: false,
              checkDisabled: !!(this.rootConfig.rowCheckDisabled && this.rootConfig.rowCheckDisabled(item)),
              selectDisabled: !!(this.rootConfig.rowSelectionDisabled && this.rootConfig.rowSelectionDisabled(item)),
              data: item
            })
          })
        }
        this.totalRowsHeight = totalRowsHeight
        this.nodes = newNodes
      },
      refreshRowClass (node) {
        let clazz = null
        if (node.selectDisabled) {
          clazz = 'dg-row-selection-disabled'
        } else if (node.isHover) {
          clazz = 'dg-row-hover'
        } else if (node.selected) {
          clazz = 'dg-row-selected'
        }
        Vue.set(node, 'clazz', clazz)
      },
      onVerticalScroll (evt) {
        this.currentVerticalScroll = evt.target.scrollTop
      },
      onHorizontalScroll (evt) {
        this.$emit('horizontal-scroll', evt.target.scrollLeft)
      },
      onContentMouseWheel (evt) {
        this.$refs.dgScrollAreaInstance.scrollTop += evt.deltaY
      },
      handleNodeCheck (node) {
        let isAllChecked = true
        _.forEach(this.nodes, item => {
          isAllChecked = isAllChecked && item.checked
          return isAllChecked
        })
        this.$emit('check-all', isAllChecked && this.nodes.length > 0)
      },
      setCheckAllstate (isAllChecked) {
        _.forEach(this.nodes, item => {
          Vue.set(item, 'checked', isAllChecked)
          if (!this.rootConfig.selectionNotEqualsChecking) {
            Vue.set(item, 'selected', isAllChecked)
            this.refreshRowClass(item)
          }
        })
        this.$emit('check-all', isAllChecked && this.nodes.length > 0)
      },
      onRowMouseOver (node) {
        Vue.set(node, 'isHover', true)
        this.refreshRowClass(node)
      },
      onRowMouseOut (node) {
        Vue.set(node, 'isHover', false)
        this.refreshRowClass(node)
      },
      onRowClick (node) {
        if (!this.selectionMultiple) {
          _.forEach(this.nodes, item => {
            if (item !== node && item.selected) {
              Vue.set(item, 'selected', false)
              this.refreshRowClass(item)
            }
          })
        }
        Vue.set(node, 'selected', !node.selected)
        if (!this.rootConfig.selectionNotEqualsChecking) {
          Vue.set(node, 'checked', node.selected)
          node._$vm && node._$vm.$emit('check', node)
        }
        this.refreshRowClass(node)
      }
    },
    watch: {
      dataSource (val) {
        this.initDataSource(val)
      }
    },
    mounted () {
      this.initDataSource(this.dataSource)
    }
  }
</script>

<style lang="scss">
  .dg-body{
    position: relative;
    overflow: hidden;
  }
  .dg-bg-container{
    > div{
      &:nth-child(odd){
        background: #eee;
      }
      &:nth-child(even){
        background: #fff;
      }
    }
  }
  .dg-body-fixed-area{
    position: relative;
    width: 100%;
    height: 100%;
    overflow-y: scroll;
    overflow-x: hidden;
  }
  .dg-bg{
  },
  .dg-rows{
    position: absolute;
    top: 0;
    left: 0;
  }
  .dg-rows-normal, .dg-rows-normal-content, .dg-rows-left, .dg-rows-right{
    position: absolute;
    top: 0;
    > div{
      position: absolute;
    }
  }
  .dg-rows-normal{
    height: 100%;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .dg-body-left-column,
  .dg-body-normal-column{
    border-right: solid 1px #DDD;
  }
  .dg-body-right-column{
    border-left: solid 1px #DDD;
  }
  .dg-rows-normal-content{
    left: 0;
  }
  .dg-row-hover{
    background: #00b3ee !important;
  }
  .dg-row-selected{
    background: #5cb85c !important;
  }
  .dg-row-selection-disabled{
    opacity: .5;
  }
  .dg-row{
    transition: .5s background;
    border-bottom: solid 1px #DDD;
  }
  .dg-body-no-data{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 10;

    > span {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
  }
  .dg-body-loading{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 10;

    &:before {
      content: '';
      line-height: 0;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: #fff;
      opacity: .5;
    }

    > span {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
  }
</style>